package com.code.common.web.resolvers;

import com.code.common.annotations.LoginAuth;
import com.code.common.util.StringUtil;
import com.code.user.model.bo.LoginTokenBO;
import com.code.user.model.po.User;
import com.code.user.token.helper.LoginTokenHelper;
import com.code.user.token.service.LoginTokenService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.annotation.Resource;
import java.lang.reflect.Method;

/**
 * 登录用户参数解析器
 *
 * @author tangyifei
 */
@Slf4j
public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver {

    @Resource
    private LoginTokenService loginTokenService;

    /**
     * 根据方法参数判断是否需要对其做转换
     *
     * @param parameter 方法参数
     * @return 对其转换与否
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        final Method method = parameter.getMethod();
        final Class<?> clazz = parameter.getMethod().getDeclaringClass();
        //类或者方法上是否有LoginAuth注解
        boolean isHasLoginAuthAnn = clazz.isAnnotationPresent(LoginAuth.class) || method.isAnnotationPresent(LoginAuth.class);
        //方法的参数类型是否是User类型
        boolean isHasLoginUserParameter = parameter.getParameterType().isAssignableFrom(User.class);
        //如果类或者方法上有LoginAuth注解并且方法的参数类型是否是User类型,那么对方法的参数进行解析并且转化
        return isHasLoginAuthAnn && isHasLoginUserParameter;
    }

    /**
     * supportsParameter方法返回true后，进入resolveArgument方法，返回值即为要转化对象的结果
     *
     * @param parameter     方法参数
     * @param mavContainer  mvc视图容器
     * @param webRequest    本地web请求对象
     * @param binderFactory web数据绑定工厂
     * @return 转换的对象
     * @throws Exception 相关的异常
     */
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        String loginTokenId = LoginTokenHelper.getLoginTokenId();
        if (StringUtil.isNotEmpty(loginTokenId)) {
            LoginTokenBO loginTokenBO = loginTokenService.getById(loginTokenId);
            if (null != loginTokenBO) {
                return loginTokenBO.getLoginUser();
            }
        }
        return User.builder();
    }
}
